package com.zt.english.activity.audio

import android.content.Context
import android.content.Intent
import android.content.res.Resources
import android.graphics.drawable.ColorDrawable
import android.media.AudioManager
import android.os.Handler
import android.text.Spannable
import android.text.SpannableString
import android.text.style.ForegroundColorSpan
import android.util.Log
import android.view.*
import android.widget.PopupWindow
import android.widget.SeekBar
import android.widget.TextView
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.zt.english.App
import com.zt.english.R
import com.zt.english.adapter.SubtitleRecycleAdapter
import com.zt.english.adapter.SubtitleRecycleAdapter.EnumVisi
import com.zt.english.bean.SubtitlesBean
import com.zt.english.databinding.ActivityAudioPlayBinding
import com.zt.english.player.AudioPlayerController
import com.zt.english.service.AudioService
import com.zt.english.utils.SrtFileParasUtil
import com.zt.english.utils.SystemUtil
import com.zt.english.utils.ToasUtils
import com.zt.english.views.RecyclerViewListDivider
import com.zt.mvvm.viewmodel.BaseViewModel
import java.text.SimpleDateFormat
import java.util.*
import java.util.concurrent.Executors
import java.util.concurrent.ScheduledFuture
import java.util.concurrent.TimeUnit

class AudioPlayViewModel : BaseViewModel<AudioPlayRepository, ActivityAudioPlayBinding>() {
    lateinit var adapter : SubtitleRecycleAdapter
    private lateinit var datas: ArrayList<SubtitlesBean>
    private val mActivity by lazy {
        mLifecycleOwner as AudioPlayActivity //类型强制转化
    }
    private lateinit var manager:LinearLayoutManager
    private var phoneBeforeIsPlaying:Boolean = false //来电/去电前是否是播放状态
    //单句循环
    private var singleSentenceLoop:Boolean = false
    val sdf = SimpleDateFormat("mm:ss")
    //顶部标题栏高度
    var topBarHeight:Int = 0
    //底部布局高度
    private var bottomHeight:Int = 0

    private var visiMode:EnumVisi = EnumVisi.ALL

    private var speed:Float = 1.0f

    //任务执行器循环周期(毫秒)
    private val peroid : Long = 200

    //上一个字幕读取的位置
    var lastPosition:Int = 0

    override fun initView() {
        mBinding.viewmodel = this
        /**
         * 标题栏设置
         */
        mBinding.include.title = "听力详情"
        mBinding.include.background = mActivity.resources.getColor(R.color.color_app_theme)
        //获取标题栏高度
        topBarHeight = mBinding.include.root.layoutParams.height
        //重新测量
        mBinding.bottom.measure(View.MeasureSpec.UNSPECIFIED,View.MeasureSpec.UNSPECIFIED)
        bottomHeight = mBinding.bottom.measuredHeight
        /**
         * 初始化音频管理器
         */
        audioManager = App.instance.getSystemService(Context.AUDIO_SERVICE) as AudioManager
        mAudioFocusListener = MyOnAudioFocusChangeListener()
        /**
         * recycleview设置滑动监听
         */
        mBinding.recycleview.addOnScrollListener(object : RecyclerView.OnScrollListener() {
            override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
                super.onScrollStateChanged(recyclerView, newState)
                System.out.println("newState:"+ newState)
                //滑动过程中停止循环任务执行器
                if(newState==RecyclerView.SCROLL_STATE_IDLE){
                    //手指离开后1s,开始执行
                    mHandler.postDelayed(Runnable {
                        if(AudioPlayerController.get().isPlaying())startExecutorUpdate()
                    },1000)
                }else{
                    stopExecutorUpdate()
                }
            }
            override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
                super.onScrolled(recyclerView, dx, dy)
            }
        })
        /**
         * seekbar滑动监听
         */
        mBinding.seekbar.setOnSeekBarChangeListener(object :SeekBar.OnSeekBarChangeListener{
            override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {

            }

            override fun onStartTrackingTouch(seekBar: SeekBar?) {

            }

            override fun onStopTrackingTouch(seekBar: SeekBar?) {
                AudioPlayerController.get().seekToPosition(seekBar?.progress?:0)
            }
        })
        /**
         * 底部popupwindow弹框
         */
        initPopWindow()

        /**
         * 注册播放状态监听
         */
        AudioPlayerController.get().registerCallback(object : AudioPlayerController.Callbacks{
            override fun onPlaybackStateChanged(state: AudioPlayerController.PlaybackState?) {
                when(state){
                    AudioPlayerController.PlaybackState.PLAYBACK_STATE_NONE ->{
                        //停止任务调度
                        stopExecutorUpdate()
                    }
                    AudioPlayerController.PlaybackState.PLAYBACK_STATE_PAUSED ->{
                        //停止任务调度
                        stopExecutorUpdate()
                    }
                    AudioPlayerController.PlaybackState.PLAYBACK_STATE_PLAYING->{
                        //开启任务调度器，每0.2s循环获取当前播放进度，更新ui
                        startExecutorUpdate()

                        /**
                         * 请求获取音频焦点。获取到焦点后其他音乐app自动暂停音乐播放，反之亦然
                         */
                        audioManager.requestAudioFocus(mAudioFocusListener,AudioManager.STREAM_MUSIC,AudioManager.AUDIOFOCUS_GAIN)
                    }
                    AudioPlayerController.PlaybackState.PLAYBACK_STATE_STOPPED->{
                        //停止任务调度
                        stopExecutorUpdate()
                    }
                    AudioPlayerController.PlaybackState.PLAYBACK_STATE_COMPLETION->{
                        //停止任务调度
                        stopExecutorUpdate()
                    }
                    AudioPlayerController.PlaybackState.PLAYBACK_STATE_ERROR->{
                        //停止任务调度
                        stopExecutorUpdate()
                        ToasUtils.show("播放失败")
                    }
                }
            }
            override fun onAudioDataChanged(duration: Int) {
                mBinding.seekbar.max = duration
                mBinding.endTv.setText(sdf.format(duration))
            }
        })
    }
    lateinit var popupWindow:PopupWindow
    private fun initPopWindow() {
        val popView: View = LayoutInflater.from(mActivity).inflate(R.layout.layout_pop_play_setting, null)
        val loopTv = popView.findViewById<TextView>(R.id.loop_play_tv)
        loopTv.setOnClickListener {
            AudioPlayerController.get().setLooping(true)
        }
        popupWindow = PopupWindow(popView)
        popupWindow.isFocusable = true
        //设置宽高
        popupWindow.setWidth(ViewGroup.LayoutParams.MATCH_PARENT)
        popView.measure(0,0)
        popupWindow.setHeight(popView.measuredHeight);
        //设置一个背景解决,某些手机窗体dismiss失败
        popupWindow.setBackgroundDrawable(ColorDrawable())
        popupWindow.setOutsideTouchable(true)
        popupWindow.setOnDismissListener(PopupWindow.OnDismissListener {

        })
    }
    fun showPopClick(view: View?) {
        if (popupWindow.isShowing) {
            popupWindow.dismiss()
        } else {
            popupWindow.showAsDropDown(view)
        }
    }
    override fun initData() {
        /**
         * 加载字幕文件:assets文件获取
         */
        val srt = mActivity.intent.getStringExtra("srt")
        val assets_ips = mActivity.resources.assets.open(srt!!)
        val list = SrtFileParasUtil.parasSrt2List(assets_ips)
        if(list!=null)initRecycleViewData(list)
    }
    fun initRecycleViewData(list : ArrayList<SubtitlesBean>){
        this.datas = list
        //设置布局管理器
        manager = LinearLayoutManager(mActivity)
        manager.orientation = LinearLayoutManager.VERTICAL
        mBinding.recycleview.layoutManager = manager
        //设置分割线
        val divider = RecyclerViewListDivider(
            mActivity,
            LinearLayoutManager.HORIZONTAL,
            SystemUtil.dp2px(15f),
            ContextCompat.getColor(mActivity, R.color.color_main_background)
        )
        mBinding.recycleview.addItemDecoration(divider)
        //设置适配器
        adapter = SubtitleRecycleAdapter(SubtitleRecycleAdapter.PlayTypeEnum.AUDIO,mActivity,list,mRepository)
        mBinding.recycleview.adapter = adapter
        //设置列表item点击事件
        adapter.itemClickListener = object : SubtitleRecycleAdapter.ItemClickListener{
            override fun itemClick(position:Int,bean: SubtitlesBean) {
                lastPosition = position
                AudioPlayerController.get().seekToPosition(bean.start)
            }
        }

        //start service to prepare auido data
        val intent = Intent(App.instance.applicationContext,AudioService::class.java)
        intent.putExtra("url",mActivity.intent.getStringExtra("url"))
        App.instance.applicationContext.startService(intent)
    }
    /**
     * 循环任务执行器
     */
    private val mExecutorService = Executors.newSingleThreadScheduledExecutor()
    private var mScheduleFuture: ScheduledFuture<*>? = null
    private val mHandler = Handler()
    fun startExecutorUpdate(){
        stopExecutorUpdate()
        if (!mExecutorService.isShutdown) {
            mScheduleFuture = mExecutorService.scheduleAtFixedRate(
                Runnable { mHandler.post(mUpdateProgressTask) },
                200,
                peroid,
                TimeUnit.MILLISECONDS
            )
        }
        mBinding.toggleIv.setImageResource(R.mipmap.icon_play)
    }
    private val mUpdateProgressTask = Runnable { updateProgress() }
    fun updateProgress(){
        val msec: Int = AudioPlayerController.get().getCurrentPosition()
        /**
         * 单句循环
         */
        if(singleSentenceLoop){
            val bean = datas.get(lastPosition)
            if((msec - bean.end) >= -peroid ){
                AudioPlayerController.get().seekToPosition(bean.start)
            }
        }
        /**
         * 获取当前音频播放时间戳对于的字幕在集合中的位置
         */
        lastPosition = searchSubPosition(msec)
        /**
         * 列表条目指定颜色变色
         */
        adapter.read(lastPosition)
        /**
         * 读取居中：
         * 滚动到顶部且距顶部屏幕高度1/2位置，从而实现读取条目居中效果
         */
        manager.scrollToPositionWithOffset(lastPosition,getHeight())
        /**
         * 更新seekbar进度条
         */
        mBinding.seekbar.progress = msec
        /**
         * 更新进度值
         */
        mBinding.startTv.setText(sdf.format(msec))
    }

    fun getHeight(): Int {
        val metrics = Resources.getSystem().displayMetrics
        val height = metrics.heightPixels - topBarHeight - bottomHeight
        return height /2 - topBarHeight
    }

    override fun onCleared() {
        super.onCleared()
        mScheduleFuture?.cancel(false)
        mExecutorService.shutdown()
    }

    /**
     * 停止执行调度器更新
     */
    private fun stopExecutorUpdate() {
        mScheduleFuture?.cancel(false)
        if(!AudioPlayerController.get().isPlaying())mBinding.toggleIv.setImageResource(R.mipmap.icon_pause)
    }
    /**
     * 采用二分法去查找当前应该播放的字幕
     *
     * @param list 全部字幕
     * @param key 播放的时间点
     * @return  返回该字幕对象
     */
    fun searchSub(list: ArrayList<SubtitlesBean>, key: Int): SubtitlesBean? {
        var start = 0
        var end: Int = list.size- 1
        while (start <= end) {
            val middle = (start + end) / 2
            if (key < list[middle].start) {
                if (key > list[middle].end) {
                    return list[middle]
                }
                end = middle - 1
            } else if (key > list[middle].end) {
                if (key < list[middle].start) {
                    return list[middle]
                }
                start = middle + 1
            } else if (key >= list[middle].start && key <= list[middle].end) {
                return list[middle]
            }
        }
        return null
    }
    /**
     * 采用二分法去查找当前应该播放的字幕
     *
     * @param list 全部字幕
     * @param key 播放的时间点
     * @return 该字幕在集合中的位置
     */
    fun searchSubPosition(key: Int): Int{
        var start = 0
        var end: Int = datas.size- 1
        while (start <= end) {
            val middle = (start + end) / 2
            if (key < datas[middle].start) {
                if (key > datas[middle].end) {
                    return middle
                }
                end = middle - 1
            } else if (key > datas[middle].end) {
                if (key < datas[middle].start) {
                    return middle
                }
                start = middle + 1
            } else if (key >= datas[middle].start && key <= datas[middle].end) {
                return middle
            }
        }
        return lastPosition
    }

    private lateinit var audioManager:AudioManager
    private lateinit var mAudioFocusListener: MyOnAudioFocusChangeListener
    /**
     * 系统音频(包括视频里的音频)焦点播放监听；实现第三方音乐app播放时本app音频播放暂停功能
     * 本回掉接口需要audioManager.requestAudioFocus（）获取焦点后才能回掉
     */
    private inner class MyOnAudioFocusChangeListener : AudioManager.OnAudioFocusChangeListener {
        override fun onAudioFocusChange(focusChange: Int) {
            Log.v("TAG", "focusChange = $focusChange")
            /**
             * focusChange
             * -1:其他app音视频播放
             * -2:来电/去电
             * 1:挂断
             */
            when(focusChange){
                -1 ->{
                    //其他app音视频播放，本app音频失去焦点
                    if(AudioPlayerController.get().isPlaying())AudioPlayerController.get().pause()
                }
                -2->{
                    //来电/去电时
                    if(AudioPlayerController.get().isPlaying()){
                        phoneBeforeIsPlaying = true
                        AudioPlayerController.get().pause()
                    }else{
                        phoneBeforeIsPlaying = false
                    }
                }
                1->{
                    //挂断
                    if(phoneBeforeIsPlaying)
                        AudioPlayerController.get().play()
                }
            }
        }
    }
    fun resultAty(){
        adapter.result()
    }

    fun toggleClick(view:View){
        if(AudioPlayerController.get().isPlaying()){
            AudioPlayerController.get().pause()
        }else{
            AudioPlayerController.get().play()
        }
    }
    //播放上一句
    fun upClick(view: View){
        if(datas.size>0){
            if(lastPosition >0){
                lastPosition--
                val item = datas.get(lastPosition)
                AudioPlayerController.get().seekToPosition(item.start)
            }
        }
    }
    //播放下一句
    fun dowmClick(view: View){
        if(datas.size>0){
            if(lastPosition < datas.size-1){
                lastPosition++
                val item = datas.get(lastPosition)
                AudioPlayerController.get().seekToPosition(item.start)
            }
        }
    }
    fun moreClick(view: View){
        //AudioPlayerController.get().startPlay("http://down010702.tingclass.com/lesson/shi0529/0001/1822/tingclass04_4479678.mp3")
        //AudioPlayerController.get().changeplayerSpeed(speed)
        showPopClick(mBinding.bottom)
    }
    fun visibiliClick(view: View){
        val start:Int
        val end:Int
        val color:Int
        when(visiMode){
            EnumVisi.ALL ->{
                visiMode = EnumVisi.EN
                start = 0
                end = 1
                color = mActivity.resources.getColor(R.color.color_app_theme)
                speed = 1.0f
            }
            EnumVisi.EN ->{
                visiMode = EnumVisi.CH
                start = 2
                end = 3
                color = mActivity.resources.getColor(R.color.color_app_theme)
                speed = 0.5f
            }
            EnumVisi.CH ->{
                visiMode = EnumVisi.NONE
                start = 0
                end = 3
                color = mActivity.resources.getColor(R.color.color_normal_word)
                speed = 2.0f
            }
            EnumVisi.NONE ->{
                visiMode = EnumVisi.ALL
                start = 0
                end = 3
                color = mActivity.resources.getColor(R.color.color_app_theme)
                speed = 0.2f
            }
        }
        adapter.visibilityEnCh(visiMode)
        val word = "E/中"
        //设置字体背景
        val spanString = SpannableString(word)
        //再构造一个改变字体颜色的Span
        val spanColor = ForegroundColorSpan(color)
        spanString.setSpan(spanColor, start,end, Spannable.SPAN_EXCLUSIVE_INCLUSIVE)
        mBinding.visibiliTv.text = spanString
    }
    fun singleLoopClick(view: View){
        if(singleSentenceLoop){
            mBinding.sentenceLoopTv.setTextColor(mActivity.resources.getColor(R.color.color_normal_word))
        }else{
            mBinding.sentenceLoopTv.setTextColor(mActivity.resources.getColor(R.color.color_app_theme))
            ToasUtils.show("单句循环")
        }
        singleSentenceLoop = !singleSentenceLoop
    }
}